﻿namespace USElections.Pages
{
    using System;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Threading;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
    using Microsoft.Phone.Controls;
    using Microsoft.Phone.Shell;
    using Microsoft.Phone.Tasks;
    using NorthernLights;
    using NorthernLights.Controls;
    using USElections.Classes;
    using USElections.Controls;
    using USElections.Model;
    using USElections.Tiles;
    using USElections.ViewModel;

    /// <summary>
    /// MainPage class.
    /// </summary>
    public partial class MainPage : PhoneApplicationPage
    {
        #region Fields
        private bool loaded = false;
        private Candidates candidates = new Candidates();
        #endregion

        /// <summary>
        /// Initializes a new instance of the MainPage class.
        /// </summary>
        public MainPage()
        {
            InitializeComponent();

            this.candidatesListBox.DataContext = this.candidates;

            UserControl voteBackTile = null;

            Candidate candidate = GetVotedCandidate();

            if (candidate != null)
            {
                voteBackTile = new VoteBackTile(candidate);
            }

            this.tilesManager.Children.Add(new TilesManager(new VoteFrontTile(), voteBackTile, new Uri("/USElections.Vote;component/Pages/VotePage.xaml", UriKind.Relative)));
            this.tilesManager.Children.Add(new CounterFrontTile());
            this.tilesManager.Children.Add(new TilesManager(new VoteResultsFrontTile(), new VoteResultsBackTile(), new Uri("/USElections.Map;component/Pages/MapPage.xaml", UriKind.Relative)));
            this.tilesManager.Children.Add(new TilesManager(new NewsFeedsFrontTile(), new NewsFeedsBackTile(), new Uri("/USElections.Newsfeed;component/Pages/NewsFeedsPage.xaml", UriKind.Relative)));
            this.tilesManager.Children.Add(new TilesManager(new CalendarFrontTile(), new CalendarBackTile(), new Uri("/USElections.Calendar;component/Pages/CalendarPage.xaml", UriKind.Relative)));
            this.tilesManager.Children.Add(new CandidatesFrontTile());
        }

        /// <summary>
        /// On Navigated To.
        /// </summary>
        /// <param name="e">The NavigationEventArgs object.</param>
        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            this.Loaded += (sender, ev) =>
            {
                if (!this.loaded)
                {
                    this.loaded = true;

                    BackgroundWorker bgw = new BackgroundWorker();
                    bgw.DoWork += (sender2, e2) =>
                    {
                        this.InitializeControls();
                    };

                    bgw.RunWorkerAsync();
                }
            };

            this.candidatesListBox.SelectedItem = null;

            if (NavigationContext.QueryString.ContainsKey(Model.Enums.Variables.CandidateId.ToString()))
            {
                try
                {
                    int id = Convert.ToInt32(NavigationContext.QueryString[Model.Enums.Variables.CandidateId.ToString()]);
                    this.NavigationContext.QueryString.Remove(Model.Enums.Variables.CandidateId.ToString());

                    this.NavigationService.Navigate(new Uri("/USElections.CandidatePage;component/Pages/CandidatePage.xaml?" + Model.Enums.Variables.CandidateId.ToString() + "=" + id, UriKind.Relative));
                }
                catch
                {
                }
            }
        }

        #region Private methods
        private void InitializeControls()
        {
            Thread.Sleep(500);

            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                // error prone.
                this.candidatesListBox.SelectedItem = null;
                this.candidatesListBox.SelectionChanged += this.CandidatesListBoxSelectionChanged;

                this.AddMyAdControl();
            });

            /* check if there was an exception that needs to be reported */
            ExceptionContainer exception = LittleWatson.GetPreviousException();

            if (exception != null)
            {
                if (LittleWatson.Instance.AllowAnonymousHttpReporting)
                {
                    LittleWatson.Instance.SendExceptionToHttpEndpoint("http://www.uselectionsapp.com/data/post.php", exception);
                }
                else
                {
                    // show popup.
                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        this.notification.Show(
                            "A problem occurred the last time you ran this application. Tap here to send an email report.",
                            new SolidColorBrush(Colors.Red),
                            () =>
                            {
                                EmailComposeTask email = new EmailComposeTask();
                                email.To = "info@uselectionsapp.com";
                                email.Subject = "US Elections App: auto-generated problem report";
                                email.Body = exception.Message + Environment.NewLine + exception.StackTrace;

                                try
                                {
                                    email.Show();
                                }
                                catch
                                {
                                }
                            });
                    });
                }
            }

            /* check if there is a new version of the app */
            string uri = string.Format("{0}?{1}", "http://www.uselectionsapp.com/data/appversion.txt", DateTime.Now.Ticks);

            NorthernLights.VersionManagement.CheckForNewVersion(
                uri,
                () =>
                {
                    Thread.Sleep(2000);

                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        this.notification.Show(
                            "An newer version of the app is available. Tap here to go the marketplace and update your app.",
                            new SolidColorBrush(Colors.Red),
                            () =>
                            {
                                MarketplaceDetailTask mdt = new MarketplaceDetailTask();
                                mdt.ContentType = MarketplaceContentType.Applications;

                                try
                                {
                                    mdt.Show();
                                }
                                catch
                                {
                                }
                            });
                    });
                });

            /* check if current voted candidate is still running, otherwise ask user to revote */
            this.CheckCurrentVote();

            /* populate running candidates list */
            this.PopulateCandidates(0);

            /* show nag for review screen */
            NagForReview.Check(NagForReview.NagType.AfterXDays | NagForReview.NagType.AfterXTimes, -1, 5);

            /* start background task */
            if (ScheduledAgentTools.GetAllowedToStart(Model.Enums.PeriodicTaskName.LiveTileUpdate))
            {
                ScheduledAgentTools.StartPeriodicAgent(Model.Enums.PeriodicTaskName.LiveTileUpdate, LiveTileVotesCastViewModel.Instance.Description);
            }
            else
            {
                ScheduledAgentTools.RemoveAgent(Model.Enums.PeriodicTaskName.LiveTileUpdate);
            }
        }

        private void CheckCurrentVote()
        {
            Candidate candidate = GetVotedCandidate();

            if (candidate != null)
            {
                // set candidate as live tile
                USElections.TileUpdates.ApplicationTile.SetPhoto();

                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    if (!candidate.Running)
                    {
                        this.notification.Show(
                            "The candidate you voted for is no longer running. Click here to change your vote.",
                            new SolidColorBrush(Colors.Orange),
                            () =>
                            {
                                this.NavigationService.Navigate(new Uri("/USElections.Vote;component/Pages/VotePage.xaml", UriKind.Relative));
                            });
                    }
                });
            }
        }

        private void PopulateCandidates(int index)
        {
            if (index < Data.Instance.RunningCandidates.Count)
            {
                BackgroundWorker bgw = new BackgroundWorker();
                bgw.DoWork += (sender, e) =>
                {
                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        Debug.WriteLine(string.Format("index: {0}", index));

                        this.candidates.Insert(index, Data.Instance.RunningCandidates[index]);
                    });

                    while (this.candidates.Count == 0 || this.candidates.Count != (index + 1))
                    {
                        Thread.Sleep(150);
                    }

                    index++;

                    Debug.WriteLine("Calling AddOneItemToListBox(" + index + ")");
                    this.PopulateCandidates(index);
                };

                bgw.RunWorkerAsync();
            }
            else
            {
                return;
            }
        }

        private void AddMyAdControl()
        {
            MyAdControl adControl = new MyAdControl();
            adControl.AdUnitId = "71671";
            adControl.Height = 80;
            adControl.Width = 480;
            adControl.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
            adControl.VerticalAlignment = System.Windows.VerticalAlignment.Top;

            Grid.SetRow(adControl, 1);
            this.LayoutRoot.Children.Add(adControl);
        }

        private void ApplicationBarIconButtonClick(object sender, EventArgs e)
        {
            ApplicationBarIconButton item = sender as ApplicationBarIconButton;

            if (item != null)
            {
                if (string.Compare(item.Text, "settings", StringComparison.InvariantCultureIgnoreCase) == 0)
                {
                    // load settings page.
                    this.NavigationService.Navigate(new Uri("/Pages/SettingsPage.xaml", UriKind.Relative));
                }
            }
        }

        private void ApplicationBarMenuItemClick(object sender, EventArgs e)
        {
            ApplicationBarMenuItem item = sender as ApplicationBarMenuItem;

            if (item != null)
            {
                if (string.Compare(item.Text, "about", StringComparison.InvariantCultureIgnoreCase) == 0)
                {
                    // load about page.
                    this.NavigationService.Navigate(new Uri("/USElections.About;component/Pages/AboutPage.xaml", UriKind.Relative));
                }
            }
        }

        private void CandidatesListBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ListBox listBox = sender as ListBox;

            if (listBox != null && listBox.SelectedItem != null)
            {
                Candidate candidate = listBox.SelectedItem as Candidate;

                if (candidate != null)
                {
                    this.NavigationService.Navigate(new Uri("/USElections.CandidatePage;component/Pages/CandidatePage.xaml?" + Model.Enums.Variables.CandidateId.ToString() + "=" + candidate.Id, UriKind.Relative));
                }
            }
        }

        private void PanoramaSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            Panorama panorama = sender as Panorama;

            if (panorama != null)
            {
                PanoramaItem item = panorama.SelectedItem as PanoramaItem;

                if (item != null)
                {
                    if (string.Compare(item.Header.ToString(), "candidates", StringComparison.InvariantCultureIgnoreCase) == 0)
                    {
                        HubTileService.UnfreezeGroup("CandidatesGroup");
                    }
                    else
                    {
                        HubTileService.FreezeGroup("CandidatesGroup");
                    }
                }
            }
        }

        private static Candidate GetVotedCandidate()
        {
            int votedcandidate = PersistentVariables.Get<int>(Model.Enums.Variables.VotedCandidate.ToString());

            if (votedcandidate != default(int))
            {
                return Data.Instance.Candidates.GetCandidateById(votedcandidate);
            }

            return null;
        }
        #endregion
    }
}